home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_053 / spreadsheet / interp.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  14KB  |  609 lines

  1. /*    SC    A Spreadsheet Calculator
  2.  *        Expression interpreter and assorted support routines.
  3.  *
  4.  *        original by James Gosling, September 1982
  5.  *        modified by Mark Weiser and Bruce Israel, 
  6.  *            University of Maryland
  7.  *
  8.  *              More mods Robert Bond, 12/86
  9.  *        Major mods to run on VMS and AMIGA, 1/17/87
  10.  */
  11.  
  12. #include "sc.h"
  13. #define DEFCOLDELIM ':'
  14.  
  15. char *malloc();
  16.  
  17. double dosum(minr, minc, maxr, maxc)
  18. int minr, minc, maxr, maxc;
  19. {
  20.     double v;
  21.     register r,c;
  22.     register struct ent *p;
  23.  
  24.     v = 0;
  25.     for (r = minr; r<=maxr; r++)
  26.     for (c = minc; c<=maxc; c++)
  27.         if ((p = tbl[r][c]) && p->flags&is_valid)
  28.         v += p->v;
  29.     return v;
  30. }
  31.  
  32. double doprod(minr, minc, maxr, maxc)
  33. int minr, minc, maxr, maxc;
  34. {
  35.     double v;
  36.     register r,c;
  37.     register struct ent *p;
  38.  
  39.     v = 1;
  40.     for (r = minr; r<=maxr; r++)
  41.     for (c = minc; c<=maxc; c++)
  42.         if ((p = tbl[r][c]) && p->flags&is_valid)
  43.         v *= p->v;
  44.     return v;
  45. }
  46.  
  47. double doavg(minr, minc, maxr, maxc)
  48. int minr, minc, maxr, maxc;
  49. {
  50.     double v;
  51.     register r,c,count;
  52.     register struct ent *p;
  53.  
  54.     v = 0;
  55.     count = 0;
  56.     for (r = minr; r<=maxr; r++)
  57.     for (c = minc; c<=maxc; c++)
  58.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  59.         v += p->v;
  60.         count++;
  61.         }
  62.  
  63.     return (v / (double)count);
  64. }
  65.  
  66. double eval(e)
  67. register struct enode *e; {
  68.     if (e==0) return 0;
  69.     switch (e->op) {
  70.     case '+':    return (eval(e->e.o.left) + eval(e->e.o.right));
  71.     case '-':    return (eval(e->e.o.left) - eval(e->e.o.right));
  72.     case '*':    return (eval(e->e.o.left) * eval(e->e.o.right));
  73.     case '/':     {    double denom = eval (e->e.o.right);
  74.             return denom ? eval(e->e.o.left) / denom : 0; }
  75.     case '<':    return (eval(e->e.o.left) < eval(e->e.o.right));
  76.     case '=':    return (eval(e->e.o.left) == eval(e->e.o.right));
  77.     case '>':    return (eval(e->e.o.left) > eval(e->e.o.right));
  78.     case '&':    return (eval(e->e.o.left) != 0.0 &&
  79.                    eval(e->e.o.right) != 0.0) ? 1.0 : 0.0;
  80.     case '|':    return (eval(e->e.o.left) != 0.0 ||
  81.                    eval(e->e.o.right) != 0.0) ? 1.0 : 0.0;
  82.     case '?':    return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
  83.                          : eval(e->e.o.right->e.o.right);
  84.     case 'm':    return (-eval(e->e.o.right));
  85.     case 'f':    return (eval(e->e.o.right));
  86.     case '~':    return (!eval(e->e.o.right));
  87.     case 'k':    return (e->e.k);
  88.     case 'v':    return (e->e.v->v);
  89.     case O_REDUCE('+'):
  90.      case O_REDUCE('*'):
  91.      case O_REDUCE('a'):
  92.         {    register r,c;
  93.         register maxr, maxc;
  94.         register minr, minc;
  95.         maxr = ((struct ent *) e->e.o.right) -> row;
  96.         maxc = ((struct ent *) e->e.o.right) -> col;
  97.         minr = ((struct ent *) e->e.o.left) -> row;
  98.         minc = ((struct ent *) e->e.o.left) -> col;
  99.         if (minr>maxr) r = maxr, maxr = minr, minr = r;
  100.         if (minc>maxc) c = maxc, maxc = minc, minc = c;
  101.             switch (e->op) {
  102.                 case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc);
  103.                  case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc);
  104.                  case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc);
  105.         }
  106.         }
  107.     }
  108. }
  109.  
  110. #define MAXPROP 7
  111.  
  112. EvalAll () {
  113.     int lastct,repct = 0;
  114.  
  115.     while ((lastct = RealEvalAll()) && (repct++ <= MAXPROP));
  116.  
  117.     repct--;
  118. }
  119.  
  120. int RealEvalAll () {
  121.     register i,j;
  122.     int chgct = 0;
  123.     register struct ent *p;
  124.     for (i=0; i<=maxrow; i++)
  125.     for (j=0; j<=maxcol; j++)
  126.         if ((p=tbl[i][j]) && p->expr) {
  127.         double v = eval (p->expr);
  128.         if (v != p->v) {
  129.             p->v = v; chgct++;
  130.             p->flags |= (is_changed|is_valid);
  131.         }
  132.         }
  133.     return(chgct);
  134. }
  135.  
  136. struct enode *new(op,a1,a2)
  137. struct enode *a1, *a2; {
  138.     register struct enode *p = (struct enode *) malloc (sizeof (struct enode));
  139.     p->op = op;
  140.     switch (op) {
  141.     case O_VAR: p->e.v = (struct ent *) a1; break;
  142.     case O_CONST: p->e.k = *(double *)&a1; break;
  143.     default: p->e.o.left = a1; p->e.o.right = a2;
  144.     }
  145.     return p;
  146. }
  147.  
  148. copy (dv, v1, v2)
  149. struct ent *dv, *v1, *v2;
  150. {
  151.     register r,c;
  152.     register struct ent *p;
  153.     register struct ent *n;
  154.     register deltar, deltac;
  155.     int maxr, maxc;
  156.     int minr, minc;
  157.     int dr, dc;
  158.  
  159.     dr = dv->row;
  160.     dc = dv->col;
  161.     maxr = v2->row;
  162.     maxc = v2->col;
  163.     minr = v1->row;
  164.     minc = v1->col;
  165.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  166.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  167.     if (dr+maxr-minr >= MAXROWS  || 
  168.            dc+maxc-minc >= MAXCOLS) {
  169.     error ("The table can't be any bigger");
  170.     return;
  171.     }
  172.     deltar = dr-minr;
  173.     deltac = dc-minc;
  174.     FullUpdate++;
  175.     for (r = minr; r<=maxr; r++)
  176.     for (c = minc; c<=maxc; c++) {
  177.         n = lookat (r+deltar, c+deltac);
  178.         clearent(n);
  179.         if (p = tbl[r][c]) {
  180.         n -> v = p -> v;
  181.         n -> flags = p -> flags;
  182.         n -> expr = copye(p->expr, deltar, deltac);
  183.         n -> label = 0;
  184.         if (p -> label) {
  185.             n -> label = (char *)
  186.                  malloc (strlen (p -> label) + 1);
  187.             strcpy (n -> label, p -> label);
  188.         }
  189.         }
  190.     }
  191. }
  192.  
  193. let (v, e)
  194. struct ent *v;
  195. struct enode *e; {
  196.     efree (v->expr);
  197.     if (constant(e)) {
  198.     v->v = eval(e);
  199.     v->expr = 0;
  200.     efree(e);
  201.     } else
  202.     v->expr = e;
  203.     v->flags |= (is_changed|is_valid);
  204.     changed++;
  205.     modflg++;
  206. }
  207.  
  208. clearent (v)
  209. struct ent *v; {
  210.     if (!v)
  211.     return;
  212.     label(v,"",-1);
  213.     v->v = 0;
  214.     if (v->expr)
  215.     efree(v->expr);
  216.     v->expr = 0;
  217.     v->flags |= (is_changed);
  218.     v->flags &= ~(is_valid);
  219.     changed++;
  220.     modflg++;
  221. }
  222.  
  223. constant(e)
  224. register struct enode *e; {
  225.     return e==0 || e->op == O_CONST 
  226.     || (e->op != O_VAR
  227.      && (e->op&~0177) != O_REDUCE(0)
  228.      && constant (e->e.o.left)
  229.      && constant(e->e.o.right));
  230. }
  231.  
  232. efree (e)
  233. register struct enode *e; {
  234.     if (e) {
  235.     if (e->op != O_VAR && e->op !=O_CONST && (e->op&~0177) != O_REDUCE(0)) {
  236.         efree (e->e.o.left);
  237.         efree (e->e.o.right);
  238.     }
  239.     free (e);
  240.     }
  241. }
  242.  
  243. label (v, s, flushdir)
  244. register struct ent *v;
  245. register char *s; {
  246.     if (v) {
  247.     if (flushdir==0 && v->flags&is_valid) {
  248.         register struct ent *tv;
  249.         if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
  250.         v = tv, flushdir = 1;
  251.         else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
  252.         v = tv, flushdir = -1;
  253.         else flushdir = -1;
  254.     }
  255.     if (v->label) free(v->label);
  256.     if (s && s[0]) {
  257.         v->label = (char *) malloc (strlen(s)+1);
  258.         strcpy (v->label, s);
  259.     } else v->label = 0;
  260.     v->flags |= is_lchanged;
  261.     if (flushdir<0) v->flags |= is_leftflush;
  262.     else v->flags &= ~is_leftflush;
  263.     FullUpdate++;
  264.     modflg++;
  265.     }
  266. }
  267.  
  268. decodev (v)
  269. register struct ent *v; {
  270.     if (v) sprintf (line+linelim, "%s%d", coltoa(v->col), v->row);
  271.     else sprintf (line+linelim,"VAR?");
  272.     linelim += strlen (line+linelim);
  273. }
  274.  
  275. char *
  276. coltoa(col)
  277. int col;
  278. {
  279.     static char rname[3];
  280.     register char *p = rname;
  281.  
  282.     if (col < 0 || col > 25*26) 
  283.     debug("coltoa: invalid col: %d", col);
  284.  
  285.     if (col > 25) {
  286.     *p++ = col/26 + 'A' - 1;
  287.     col %= 26;
  288.     }
  289.     *p++ = col+'A';
  290.     *p = 0;
  291.     return(rname);
  292. }
  293.  
  294. decompile(e, priority)
  295. register struct enode *e; {
  296.     register char *s;
  297.     if (e) {
  298.     int mypriority;
  299.     switch (e->op) {
  300.     default: mypriority = 99; break;
  301.     case '?': mypriority = 1; break;
  302.     case ':': mypriority = 2; break;
  303.     case '|': mypriority = 3; break;
  304.     case '&': mypriority = 4; break;
  305.     case '<': case '=': case '>': mypriority = 6; break;
  306.     case '+': case '-': mypriority = 8; break;
  307.     case '*': case '/': mypriority = 10; break;
  308.     }
  309.     if (mypriority<priority) line[linelim++] = '(';
  310.     switch (e->op) {
  311.     case 'f':    { 
  312.                 for (s="fixed "; line[linelim++] = *s++;);
  313.                 linelim--;
  314.                 decompile (e->e.o.right, 30);
  315.                 break;
  316.             }
  317.     case 'm':    line[linelim++] = '-';
  318.             decompile (e->e.o.right, 30);
  319.             break;
  320.     case '~':    line[linelim++] = '~';
  321.             decompile (e->e.o.right, 30);
  322.             break;
  323.     case 'v':    decodev (e->e.v);
  324.             break;
  325.     case 'k':    sprintf (line+linelim,"%.8g",e->e.k);
  326.             linelim += strlen (line+linelim);
  327.             break;
  328.     case O_REDUCE('+'):
  329.             for (s="@sum("; line[linelim++] = *s++;);
  330.             goto more;
  331.     case O_REDUCE('*'):
  332.             for (s="@prod("; line[linelim++] = *s++;);
  333.             goto more;
  334.     case O_REDUCE('a'):
  335.             for (s="@avg("; line[linelim++] = *s++;);
  336.     more:        linelim--;
  337.             decodev (e->e.o.left);
  338.             line[linelim++] = ':';
  339.             decodev (e->e.o.right);
  340.             line[linelim++] = ')';
  341.             break;
  342.  
  343.     default:    decompile (e->e.o.left, mypriority);
  344.             line[linelim++] = e->op;
  345.             decompile (e->e.o.right, mypriority+1);
  346.             break;
  347.     }
  348.     if (mypriority<priority) line[linelim++] = ')';
  349.     } else line[linelim++] = '?';
  350. }
  351.  
  352. editv (row, col) {
  353.     sprintf (line, "let %s%d = ", coltoa(col), row);
  354.     linelim = strlen(line);
  355.     editexp(row,col);
  356. }
  357.  
  358. editexp(row,col) {
  359.     register struct ent *p;
  360.     p = lookat (row, col);
  361.     if (p->flags&is_valid)
  362.     if (p->expr) {
  363.         decompile (p->expr);
  364.         line[linelim] = 0;
  365.     } else {
  366.         sprintf (line+linelim, "%.8g", p->v);
  367.         linelim += strlen (line+linelim);
  368.     }
  369. }
  370.  
  371. edits (row, col) {
  372.     register struct ent *p = lookat (row, col);
  373.     sprintf (line, "%sstring %s%d = \"",
  374.             ((p->flags&is_leftflush) ? "left" : "right"),
  375.             coltoa(col), row);
  376.     linelim = strlen(line);
  377.     sprintf (line+linelim, "%s", p->label);
  378.     linelim += strlen (line+linelim);
  379. }
  380.  
  381. printfile (fname) {
  382.     FILE *f = fopen(fname, "w");
  383.     char pline[1000];
  384.     int plinelim;
  385.     register row, col;
  386.     register struct ent **p;
  387.     if (f==0) {
  388.     error ("Can't create %s", fname);
  389.     return;
  390.     }
  391.     for (row=0;row<=maxrow; row++) {
  392.     register c = 0;
  393.     plinelim = 0;
  394.     for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
  395.         if (*p) {
  396.         char *s;
  397.         while (plinelim<c) pline[plinelim++] = ' ';
  398.         plinelim = c;
  399.         if ((*p)->flags&is_valid) {
  400.             sprintf (pline+plinelim,"%*.*f",fwidth[col],precision[col],
  401.                 (*p)->v);
  402.             plinelim += strlen (pline+plinelim);
  403.         }
  404.         if (s = (*p)->label) {
  405.             register char *d;
  406.             d = pline+((*p)->flags&is_leftflush
  407.             ? c : c-strlen(s)+fwidth[col]);
  408.             while (d>pline+plinelim) pline[plinelim++] = ' ';
  409.             if (d<pline) d = pline;
  410.             while (*s) *d++ = *s++;
  411.             if (d-pline>plinelim) plinelim = d-pline;
  412.         }
  413.         }
  414.         c += fwidth [col];
  415.     }
  416.     fprintf (f,"%.*s\n",plinelim,pline);
  417.     }
  418.     fclose (f);
  419. }
  420.  
  421. tblprintfile (fname) {
  422.     FILE *f = fopen(fname, "w");
  423.     char pline[1000];
  424.     int plinelim;
  425.     register row, col;
  426.     register struct ent **p;
  427.     char coldelim = DEFCOLDELIM;
  428.  
  429.     if (f==0) {
  430.     error ("Can't create %s", fname);
  431.     return;
  432.     }
  433.     for (row=0;row<=maxrow; row++) {
  434.     register c = 0;
  435.     plinelim = 0;
  436.     for (p = &tbl[row][col=0]; col<=maxcol; col++, p++) {
  437.         if (*p) {
  438.         char *s;
  439.         if ((*p)->flags&is_valid) {
  440.             fprintf (f,"%.*f",precision[col],
  441.                 (*p)->v);
  442.         }
  443.         if (s = (*p)->label) {
  444.                 fprintf (f,"%s",s);
  445.         }
  446.         }
  447.         fprintf(f,"%c",coldelim);
  448.     }
  449.     fprintf (f,"\n",pline);
  450.     }
  451.     fclose (f);
  452. }
  453.  
  454. struct enode *copye (e, Rdelta, Cdelta)
  455. register struct enode *e; {
  456.     register struct enode *ret;
  457.     if (e==0) ret = 0;
  458.     else {
  459.     ret = (struct enode *) malloc (sizeof (struct enode));
  460.     ret->op = e->op;
  461.     switch (ret->op) {
  462.     case 'v':
  463.         ret->e.v = lookat (e->e.v->row+Rdelta, e->e.v->col+Cdelta);
  464.         break;
  465.     case 'k':
  466.         ret->e.k = e->e.k;
  467.         break;
  468.     case 'f':
  469.         ret->e.o.right = copye (e->e.o.right,0,0);
  470.         ret->e.o.left = 0;
  471.          break;
  472.      case O_REDUCE('+'):
  473.      case O_REDUCE('*'):
  474.      case O_REDUCE('a'):
  475.          ret->e.o.right = (struct enode *) lookat (
  476.                    ((struct ent *)e->e.o.right)->row+Rdelta,
  477.                    ((struct ent *)e->e.o.right)->col+Cdelta
  478.             );
  479.          ret->e.o.left = (struct enode *) lookat (
  480.                    ((struct ent *)e->e.o.left)->row+Rdelta,
  481.                    ((struct ent *)e->e.o.left)->col+Cdelta
  482.             );
  483.         break;
  484.     default:
  485.         ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
  486.         ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
  487.         break;
  488.     }
  489.     }
  490.     return ret;
  491. }
  492.  
  493. /*
  494.  * sync_refs and sync_ref are used to remove references to
  495.  * deleted struct ents.  Note that the deleted structure must still
  496.  * be hanging around before the call, but not referenced by an entry
  497.  * in tbl.  Thus the free_ent, fix_ent calls in sc.c
  498.  */
  499.  
  500. sync_refs () {
  501.     register i,j;
  502.     register struct ent *p;
  503.     for (i=0; i<=maxrow; i++)
  504.     for (j=0; j<=maxcol; j++)
  505.         if ((p=tbl[i][j]) && p->expr)
  506.         sync_ref(p->expr);
  507. }
  508.  
  509.  
  510. sync_ref(e)
  511. register struct enode *e;
  512. {
  513.     if (e==0)
  514.     return;
  515.     else {
  516.     switch (e->op) {
  517.     case 'v':
  518.         e->e.v = lookat(e->e.v->row, e->e.v->col);
  519.         break;
  520.     case 'k':
  521.         break;
  522.      case O_REDUCE('+'):
  523.      case O_REDUCE('*'):
  524.      case O_REDUCE('a'):
  525.          e->e.o.right = (struct enode *) lookat (
  526.                    ((struct ent *)e->e.o.right)->row,
  527.                    ((struct ent *)e->e.o.right)->col
  528.             );
  529.          e->e.o.left = (struct enode *) lookat (
  530.                    ((struct ent *)e->e.o.left)->row,
  531.                    ((struct ent *)e->e.o.left)->col
  532.             );
  533.         break;
  534.     default:
  535.         sync_ref(e->e.o.right);
  536.         sync_ref(e->e.o.left);
  537.         break;
  538.     }
  539.     }
  540. }
  541.  
  542. hiderow(arg)
  543. {
  544.     register int r1;
  545.     register int r2;
  546.  
  547.     r1 = currow;
  548.     r2 = r1 + arg - 1;
  549.     if (r1 < 0 || r1 > r2) {
  550.     error("Invalid Range");
  551.     return;
  552.     }
  553.     if (r2 > MAXROWS-2) {
  554.     error("You can't hide the last row");
  555.     return;
  556.     }
  557.     FullUpdate++;
  558.     while (r1 <= r2)
  559.     hidden_row[r1++] = 1;
  560. }
  561.  
  562. hidecol(arg)
  563. {
  564.     register int c1;
  565.     register int c2;
  566.  
  567.     c1 = curcol;
  568.     c2 = c1 + arg - 1;
  569.     if (c1 < 0 || c1 > c2) {
  570.     error("Invalid Range");
  571.     return;
  572.     }
  573.     if (c2 > MAXCOLS-2) {
  574.     error("You can't hide the last col");
  575.     return;
  576.     }
  577.     FullUpdate++;
  578.     while (c1 <= c2)
  579.     hidden_col[c1++] = 1;
  580. }
  581.  
  582. showrow(r1, r2)
  583. {
  584.     if (r1 < 0 || r1 > r2) {
  585.     error("Invalid Range");
  586.     return;
  587.     }
  588.     if (r2 > MAXROWS-1) {
  589.     r2 = MAXROWS-1;
  590.     }
  591.     FullUpdate++;
  592.     while (r1 <= r2)
  593.     hidden_row[r1++] = 0;
  594. }
  595.  
  596. showcol(c1, c2)
  597. {
  598.     if (c1 < 0 || c1 > c2) {
  599.     error("Invalid Range");
  600.     return;
  601.     }
  602.     if (c2 > MAXCOLS-1) {
  603.     c2 = MAXCOLS-1;
  604.     }
  605.     FullUpdate++;
  606.     while (c1 <= c2)
  607.     hidden_col[c1++] = 0;
  608. }
  609.